package com.sztz.excel;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.sztz.result.BaseResult;
import com.sztz.result.ResultEnum;
import com.sztz.result.ServiceException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 固定格式的Excel读取监听器抽象类，带数据校验功能
 * @author yzy
 * @date 2022/8/19 15:59
 */
@Slf4j
public abstract class AbstractFixedFormatExcelListener<T> extends AnalysisEventListener<T> {
    /**
     * 每批次最大处理行数
     */
    private int batchCount = 100;
    /**
     *创建list集合封装最终的数据
     */
    private List<T> dataList = new ArrayList<>();
    /**
     *创建list集合封装异常提示数据
     */
    private List<String> errorList = new ArrayList<>();
    /**
     * 解析数据的具体处理方法
     */
    private Consumer<List<T>> consumer;

    public AbstractFixedFormatExcelListener(Consumer<List<T>> consumer){
        this.consumer = consumer;
    }
    /**
     * 解析到的数据处理
     * @param data 解析出的数据
     * @param context 解析上下文
     * @author yzy
     * @date 2022/8/03 11:22
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        BaseResult<String> apply = validate(data,context.readRowHolder().getRowIndex()+1);
        if(apply.isFail()){
            //校验不通过就记录数据异常信息
            errorList.add(apply.getData());
            //清空已解析的数据
            dataList.clear();
        }
        //没有错误时才需要处理数据
        if(CollUtil.isEmpty(errorList)) {
            dataList.add(data);
            if (batchCount <= dataList.size()) {
                log.info("共解析到{}行数据", dataList.size());
                consumer.accept(dataList);
                dataList.clear();
            }
        }
    }
    /**
     * 最后剩下的数据处理
     * @param context 解析上下文
     * @author yzy
     * @date 2022/8/03 11:22
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if(CollUtil.isNotEmpty(dataList)){
            log.info("最后解析到{}行数据",dataList.size());
            consumer.accept(dataList);
        }
        log.info("所有数据解析完成！");
        //校验不通过就抛出异常，异常信息就是校验方法返回的信息
        if(CollUtil.isNotEmpty(errorList)){
            throw new ServiceException(ResultEnum.VALIDATE_ERROR.getCode(), JSONUtil.toJsonStr(errorList));
        }
    }
    /**
     * 对解析出的数据进行校验，具全实现方法由子类实现
     * @param data 解析出的一行数据
     * @return BaseResult<String> 校验结果
     * @author yzy
     * @date 2022/8/19 17:02
     */
    public abstract BaseResult<String> validate(T data,int rowIndex);
    /**
     * 可以设置每批次的数据
     */
    public void setBatchCount(int batchCount){
        this.batchCount = batchCount;
    }
}
